TLS : TLS / SSL communication

更新时间:
2024-05-13
下载文档

TLS : TLS / SSL communication

Tls is an encrypted communication module that provides TLS / SSL communication support. This module uses methods similar to Tcp module.

Like the Tcp module, the JSRE Tls module also supports multitasking mode.

User can use the following code to import the Tls module.

var Tls = require('tls');

Support

The following shows Tls module APIs available for each permissions.

 User ModePrivilege Mode
Tls.createSerCtx
Tls.createServer
Tls.createClient
Tls.createByFd
tls.sockFd
tls.addcert
tls.accept
tls.send
tls.recv
tls.pending
tls.mports 
tls.error
tls.close
tls.flyAway
tls.isEOF
tls.sockName
tls.peerName
tls.bindToDevice
tls.setKeepAlive
tls.setNoDelay
tls.setLinger
tls.setTTL
tls.setReuseAddr
tls.setIPv6Only
tls.getState
tls.getRecvBufferSize
tls.getSendBufferSize
tls.setRecvBufferSize
tls.setSendBufferSize

Tls Class

Tls.createSerCtx(opt)

  • opt {Object} Tls server option.
  • Returns: {Object} Tls object.

Create a TLS server context used to TCP server upgrade to TLS server. opt.name must exist. This function is mostly used internally and will not be introduced in detail here.

Tls.createServer(opt, sockaddr[, backlog[, dev]])

  • opt {Object} Tls server option.
  • sockaddr {Object} Local address.
  • backlog {Integer} Number of outstanding connections. default: 5.
  • dev {String} The network interface you want to bind. default: not bind.
  • Returns: {Object} Tls object.

opt includes following items:

  • name {String} Server name for multitasking. If it is a single task server, this can be undefined.
  • ca {String} Optional trusted CA certificates to verify client certificate. default: no CA certificates.
  • cert {String} Server certificate.
  • key {String} Private key of server certificate.
  • passwd {String} Private key password. default: no password.
  • ipcert {Boolean} If the client does not send the SNI option, whether to find the corresponding IP signature certificate. default: false.
  • renegotiate {Boolean} If this server support renegotiate. default: false.
  • handshakeTimeout {Integer} TLS handshake maximum timeout (2000 ~ 120000). default: 60000.

sockaddr includes following items:

  • domain {Integer} Address domain: socket.AF_INET or socket.AF_INET6.
  • addr {String} Address.
  • port {Integer} Port.

Create a TLS server and bind to the specified address. If the port is 0, the system automatically assigns a port. The port number assigned by the system can be obtained through the tls.sockName() function.

EdgerOS 1.6.5 and later versions, domain can use Tls.AF_INET and Tls.AF_INET6; EdgerOS 1.10.1 and later versions, The domain member can be omitted.

Example

var option = {
  name: 'Tls-Server1',
  cert: fs.readString('./cert.pem')
};

var saddr = Tls.sockaddr(Tls.INADDR_ANY, 3000);
var tls = Tls.createServer(option, saddr);

Tls.createClient(opt, sockaddr[, timeout])

  • opt {Object} Tls client option.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means timeout with default connect timeout setting.
  • Returns: {Object} Tls object.

opt includes following items:

  • rejectUnauthorized {Boolean} Whether the server certificate should be verified against the list of supplied CAs. default: false.
  • loadDefaultCerts {Boolean} Whether to load JSRE / EdgerOS environment default trusted certificates. default: false.
  • ca {String} Trusted CA certificates chain. default: undefined.
  • server {String} Set the server host name (usually is the server host name) to verify received server certificate. default: undefined.
  • renegotiate {Boolean} If this client support renegotiate. default: false.
  • handshakeTimeout {Integer} TLS handshake maximum timeout (2000 ~ 120000). default: 60000.

If you need authentication between the server and the client, you can specify the client certificate and private key through the following members of opt:

  • cert {String} Client certificate.
  • key {String} Private key of client certificate.
  • passwd {String} Private key password. default: no password.

Create a TLS client and connects to the specified remote host. Use synchronous mode.

Example

var option = {
  rejectUnauthorized: true,
  ca: fs.readString('./ca.pem'),
  server: 'www.example.com'
};

var saddr = Tls.sockaddr('192.168.0.3', 3000);
var tls = Tls.createClient(option, saddr);
if (!tls) {
  console.log('connect error:', sys.error());
}

Tls.createClient(opt, sockaddr, callback)

  • opt {Object} Tls client option.
  • sockaddr {Object} Remote address.
  • callback {Function} Tls connected (tcp connect and tls handshake) callback.
    • tls {Object} Tls object.
    • remote {Object} Remote address. EdgerOS 1.6.5 and later versions add this argument.
  • Returns: {Object} Tls object.

Create a Tls client and connects to the specified remote host. Use asynchronous mode.

Example

var option = {
  rejectUnauthorized: false,
  loadDefaultCerts: true
};

var saddr = Tls.sockaddr('192.168.0.3', 3000);
var tls = Tls.createClient(option, saddr, (tls) => {
  console.log('Connected');
});

while (true) {
  iosched.poll(); // callback() will called here.
}

Tls.createByFd(name, sockFd[, timeout])

  • name {String} Server name for multitasking.
  • sockFd {Integer} Socket file descriptor, MUST tcp socket descriptor.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means timeout with default handshake timeout setting.
  • Returns: {Object} Tls object.

Create a tls object with socket file descriptor, mainly used to multitasking TLS server. Use synchronous mode.

Example

var tls = Tls.createByFd('Tls-Server1', sockFd);

Tls.createByFd(name, sockFd, callback)

  • name {String} Server name for multitasking.
  • sockFd {Integer} Socket file descriptor, MUST tcp socket descriptor.
  • callback {Function} Handshaked callback.
    • tls {Object} Tls object.
  • Returns: {Object} Tls object.

Create a tls object with socket file descriptor, mainly used to multitasking TLS server. Use asynchronous mode.

Example

var tls = Tls.createByFd('Tls-Server1', sockFd, (tls) => {
  console.log('Client handshaked!');
});

while (true) {
  iosched.poll(); // callback() will called here.
}

Tls Object

tls.sockFd

  • {Integer}

The tls object socket file descriptor. Only for iosched readable event detection in current tasks.

tls.accept([remoteAddr[, timeout]])

  • remoteAddr {Object} Remote connector address. default: undefined (does not care).
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Object} Tls object.

The Tls.accept() function shall extract the first connection on the queue of tls pending connections, and create a new tls object. Use synchronous mode.

Example

var remoteAddr = {};
var tlsNew = tls.accept(remoteAddr);
if (tlsNew) {
  console.log('New remote connected:', remoteAddr);
}

tls.addcert(opt)

  • opt {Object} Tls server option.
  • Returns: {Boolean} Whether it was added successfully.

opt includes following items:

  • name {String} Server host name.
  • ca {String} Optional trusted CA certificates. default: no CA certificates.
  • cert {String} Server certificate.
  • key {String} Private key of server certificate.
  • passwd {String} Private key password. default: no password.

This method adds a SNI (Server Name Indication) certificate to the tls server. SNI is an extension used to improve SSL or TLS for servers. It mainly solves the disadvantage that one server can only use one certificate (one host name). With the support of the server for virtual hosts, one server can provide services for multiple host names, so SNI must be supported to meet the demand.

Example

tls.addcert({
  name: 'demo.mysite.com',
  cert: fs.readString('./cert.crt'),
  key: fs.readString('./cert.key')
});

tls.accept(unused, callback)

  • unused {Undefined} Asynchronous mode does not use this argument.
  • callback {Function} Remote connected callback.
    • tls {Object} New Tls object.
    • remoteAddr {Object} Remote address.

The tls.accept() function shall extract the first connection on the queue of tls pending connections, and create a new tls object. Use asynchronous mode.

Example

tls.accept(undefined, (newTls, remoteAddr) => {
  console.log('New remote connected:', remoteAddr);
});

while (true) {
  iosched.poll(); // callback() will called here.
}

tls.send(string[, timeout])

  • string {String} String to be send.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually sent, negative error.

The tls.send() function shall initiate transmission of a message from the specified socket to its peer.

Example

var num = tls.send('Hello Packet!');
if (num < 0) {
  console.log('send error:', sys.error());
}

tls.send(buffer[, offset[, length[, timeout]]])

  • buffer {Buffer} Write data buffer.
  • offset {Integer} Buffer offset. default:0.
  • length {Integer} Write length. default:buffer.length.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually sent, negative error.

The tls.send() function shall initiate transmission of a message from the specified socket to its peer.

Example

var buf = new Buffer([1, 2, 3]);

var num = tls.send(buf);
if (num < 0) {
  console.log('send error:', sys.error());
}

tls.recv(buffer[, offset[, length[, timeout]]])

  • buffer {Buffer} Receive buffer.
  • offset {Integer} Buffer offset. default:0.
  • length {Integer} Receive length limit. default:buffer.length.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually receive, negative error.

The tls.recv() function shall receive a message from a connection-mode socket.

Example

var buf = new Buffer(1024);

var num = tls.recv(buf);
if (num < 0) {
  console.log('recv error:', sys.error());
}

tls.pending()

  • Returns: {Integer} The number of bytes in tls buffer.

Get the number of readable bytes in the tls buffer.

Example

var num = tls.pending();
if (num > 0) {
  tls.recv(buf);
}

tls.mports(mports)

  • mports {Integer} Number of consecutive ports to be added.

This function can set a LISTEN state tcp file descriptor for multi-port listening, starting with the port when bind(), set the number of additional listening continuous ports.

Example

var option = {
  name: 'Tls-Server1',
  cert: fs.readString('./cert.pem')
};

var saddr = Tls.sockaddr(Tls.INADDR_ANY, 2049);
var tls = Tls.createServer(option, saddr);
tls.mports(5); // add listen ports: 2050, 2051, 2052, 2053, 2054

tls.error()

  • Returns: {Integer} Last socket errno.

Get socket error status and clears it (set to zero). most like (C language):

getsockopt(sockFd, SOL_SOCKET, SO_ERROR, (void *)&err, &len);

Example

var errno = tls.error();
if (errno) {
  console.log('socket error:', sys.error(errno));
}

tls.close()

Close tls connect.

tls.flyAway()

This function is only used in multitasking mode. Clear the object internal file descriptor and do not recycle the file descriptor. This method is used for file descriptor delivery between multitasking, to prevent system errors from reclaiming file descriptors.

Example

  • main.js
var newTls = tls.accept();

// Send file descriptor to other task.
Task.send(otherTask.id(), { sockFd: newTls.sockFd });

// MUST Call flyAway() and cannot use this object again.
newTls.flyAway();
  • task.js
var msg = Task.recv();

// Create a tls object by sockFd.
var tls = Tls.createByFd('ServerName', msg.sockFd);

tls.isEOF()

  • Returns: {Boolean} Whether the TCP socket receives complete data. (EOF)

This function is used to judge whether the TCP connection has received complete data. This function must follow the recv function. When this function return a negative number, it means that the TCP connection is disconnected. You can judge whether the reception is complete through the isEOF function. This function is valid on EdgerOS 2.0.0 and above.

Example

var num = tls.recv(...);
if (num < 0) {
  if (tls.isEOF()) {
    console.log('receives complete data');
  }
}

tls.sockName()

  • Returns: {Object} Local sockaddr.

The tls.sockName() function shall retrieve the locally-bound name of the specified socket.

Example

var saddr = tls.sockName();
console.log(saddr);

tls.peerName()

  • Returns: {Object} Remote sockaddr.

The tls.peerName() function shall retrieve the peer address of the specified socket.

Example

var saddr = tls.peerName();
console.log(saddr);

tls.bindToDevice([ifname])

  • ifname {String} Network interface name. default: all network interface.
  • Returns: {Boolean} Whether the operation was successful.

The tls.bindToDevice() function binds the network sending and receiving to the specified network interface, and the data packet is only allowed to be sent and received using this network interface.

Example

tls.bindToDevice('en1');

tls.setKeepAlive(enable[, idle[, interval[, count]]])

  • enable {Boolean} Whether to enable the keepalive.
  • idle {Integer} The time (in milliseconds) the connection needs to remain idle before TCP starts sending keepalive probes. If enable is true, must have this parameter.
  • interval {Integer} The time (in milliseconds) between individual keepalive probes. default: idle.
  • count {Integer} The maximum number of keepalive probes TCP should send before dropping the connection. default: 3.
  • Returns: {Boolean} Whether the operation was successful.

Keeps connections active by enabling the periodic transmission of messages.

Example

tls.setKeepAlive(true, 6000);

tls.setNoDelay(enable)

  • enable {Boolean} Whether to enable the no delay.
  • Returns: {Boolean} Whether the operation was successful.

For TCP NO DEALY, please refer to Nagle's Algorithm and Delayed ACK related articles, which are not described here. If TCP is used for interactive commands, it is recommended to enable.

Example

tls.setNoDelay(true);

tls.setLinger(linger)

  • linger {Object} Liger option.
  • Returns: {Boolean} Whether the operation was successful.

linger includes following items:

  • onoff {Boolean} On: true, Off: false:.
  • time {Integer} Linger time expires in seconds.

If linger.onoff is nonzero and linger.time is nonzero, then the kernel will linger when the socket is closed. That is, if there is any data still remaining in the socket send buffer, the process is put to sleep until either: all the data is sent and acknowledged by the peer TCP, or the linger time expires.

Example

tls.setLinger({ onoff: true, time: 0 });

tls.setTTL(timeToLive)

  • timeToLive {Integer} IP TTL: 0 ~ 255.
  • Returns: {Boolean} Whether the operation was successful.

Changes the specified tcp TTL value of the IP header.

Example

tls.setTTL(64);

tls.setReuseAddr(enable)

  • enable {Boolean} Whether to enable reuse address.
  • Returns: {Boolean} Whether the operation was successful.

Specifies that the rules used in validating addresses supplied to Tls.createServer() should allow reuse of local addresses. Tls.createServer() has enabled reuse attribute by default, it is recommended not to disable.

Example

tls.setReuseAddr(true);

tls.setIPv6Only(enable)

  • enable {Boolean} Whether to only enable IPv6.
  • Returns: {Boolean} Whether the operation was successful.

If this flag is set to true, then the tls is re‐stricted to sending and receiving IPv6 packets only.

Example

tls.setIPv6Only(false);

tls.getState()

  • Returns: {Integer} TLS tcp state, negative on error.

Get the current TLS tcp connect state.

The return value will be one of the following values:

  • socket.TCP_CLOSED
  • socket.TCP_LISTEN
  • socket.TCP_SYN_SENT
  • socket.TCP_SYN_RCVD
  • socket.TCP_ESTABLISHED
  • socket.TCP_FIN_WAIT_1
  • socket.TCP_FIN_WAIT_2
  • socket.TCP_CLOSE_WAIT
  • socket.TCP_CLOSING
  • socket.TCP_LAST_ACK
  • socket.TCP_TIME_WAIT

Example

var state = tls.getState();

tls.getRecvBufferSize()

  • Returns: {Integer} Receive buffer size, negative on error.

Get current receive buffer size in bytes.

tls.getSendBufferSize()

  • Returns: {Integer} Send buffer size, negative on error.

Get current send buffer size in bytes.

tls.setRecvBufferSize(size)

  • size {Integer} Receive buffer size. Must be between 1024bytes and 16Mbytes.
  • Returns: {Boolean} Whether the operation was successful.

Set current receive buffer size in bytes.

tls.setSendBufferSize(size)

  • size {Integer} Send buffer size. Must be between 1024bytes and 16Mbytes.
  • Returns: {Boolean} Whether the operation was successful.

Set current send buffer size in bytes.

Synchronous to asynchronous

JSRE provides a synchronous multitasking model. Like other language environments, it also provides an asynchronous processing model. You can choose any way to develop application, even in one application, depending on the characteristics of the different transactions, you can using different methods at one application.

If you are very familiar with asynchronous development, the following method here can convert synchronization to asynchronous.

Server

Example

var EventEmitter = require('events');
var Tls = require('tls');
var fs = require('fs');
var iosched = require('iosched');

var option = {
  cert: fs.readString('./cert.pem')
};

var saddr = Tls.sockaddr(Tls.INADDR_ANY, 2049);
var server = Tls.createServer(option, saddr);

function onMessage(client, buffer, num) {
  console.log('Client:', client.peerName().addr, 'Say:', buffer.toString(num));
}

server.accept(undefined, (client, remoteAddr) => {
  console.log('New client:', remoteAddr);
  EventEmitter.inherits(client);
  client.on('message', onMessage);
  client.revent = iosched.event(iosched.READ, client.sockFd,
  (client) => {
    var buffer = new Buffer(4096);
    var ret = true;
    do {
      var num = client.recv(buffer, 0, buffer.length, 0);
      if (num > 0) {
        client.emit('message', client, buffer, num);
      } else if (num < 0) {
        ret = false;
        console.log('Client lost:', client.peerName());
        client.close();
      }
    } while (num > 0);
    return ret;
  }, undefined, client);
  iosched.add(client.revent);
});

while (true) {
  iosched.poll();
}

Client

Example

var EventEmitter = require('events');
var Tls = require('tls');
var fs = require('fs');
var iosched = require('iosched');

var option = {
  rejectUnauthorized: false,
  ca: fs.readString('./ca.pem')
};

var saddr = Tls.sockaddr('192.168.0.2', 2049);
var client = Tls.createClient(option, saddr, (client) => {
  client.send('Hello I am client ^_^');
  client.send('Goodbye!');
  client.close();
});

while (true) {
  iosched.poll();
}

Multi-Task Server

Example

  • main.js
var Tls = require('tls');
var fs = require('fs');
var iosched = require('iosched');

// Two Task Server.
var next = 0;
var task = [];
task[0] = new Task('./task.js');
task[1] = new Task('./task.js');

var option = {
  name: 'TLS-Server1',
  cert: fs.readString('./cert.pem')
};

var saddr = Tls.sockaddr(Tls.INADDR_ANY, 2049);
var server = Tls.createServer(option, saddr);

server.accept(undefined, (client, remoteAddr) => {
  console.log('New client:', remoteAddr);
  // The file descriptor is passed to other tasks and will be closed by other tasks.
  task[next].send({ sockFd: client.sockFd });
  // MUST Call flyAway()
  client.flyAway();
  if (++next > 1) {
    next = 0;
  }
});

while (true) {
  iosched.poll();
}
  • task.js
var Tls = require('tls');
var socket = require('socket');
var iosched = require('iosched');

function onMessage(client, buffer, num) {
  console.log('Client:', client.peerName().addr, 'Say:', buffer.toString(num));
}

Task.on('message', function(msg, from) {
  if (!msg && msg.sockFd < 0) {
    return;
  }
  var client = Tls.createByFd('TLS-Server1', msg.sockFd, 500); // handshake timeout: 500ms
  if (!client) {
    return; // handshake error.
  }
  EventEmitter.inherits(client);
  client.on('message', onMessage);
  client.revent = iosched.event(iosched.READ, client.sockFd,
  (client) => {
    var buffer = new Buffer(4096);
    var ret = true;
    do {
      var num = client.recv(buffer, 0, buffer.length, 0);
      if (num > 0) {
        client.emit('message', client, buffer, num);
      } else if (num < 0) {
        ret = false;
        console.log('Client lost:', client.peerName());
        client.close();
      }
    } while (num > 0);
    return ret;
  }, undefined, client);
  iosched.add(client.revent);
});

iosched.forever();

In task.js, tls.createByFd() has a blocking handshake. Can it be transformed into a full asynchronous non-blocking mode?

Tls Module Constant

Tls.AF_INET

  • {Integer} 2

Tls.AF_INET6

  • {Integer} 10

Tls.INADDR_NONE

  • {String} '255.255.255.255'

Tls.INADDR_LOOPBACK

  • {String} '127.0.0.1'

Tls.INADDR_ANY

  • {String} '0.0.0.0'

Tls.INADDR_BROADCAST

  • {String} '255.255.255.255'

Tls.IN6ADDR_ANY

  • {String} '::'

Tls.IN6ADDR_LOOPBACK

  • {String} '::1'

Tls.IN6ADDR_NODELOCAL_ALLNODES

  • {String} 'ff01::1'

Tls.IN6ADDR_LINKLOCAL_ALLNODES

  • {String} 'ff02::1'

Tls.IN6ADDR_LINKLOCAL_ALLROUTERS

  • {String} 'ff01::2'
文档内容是否对您有所帮助?
有帮助
没帮助